三种静态查找算法:顺序、二分/折半、索引/分块查找

终于找了个时间,把三种静态查找算法简单总结了一下,与大家分享讨论。

完整源代码下载地址

顺序查找

简介

  顺序查找是在一个已知无(或有序)序队列中找出与给定关键字相同的数的具体位置。原理是让关键字与队列中的数逐个比较,直到找出与给定关键字相同的数为止。

代码实现
public static int orderSearch(int arr[], int target) {
	for (int i = 0; i < arr.length; i++)
		if (arr[i] == target)
			return i;
		return -1;
	}
性能分析

  时间复杂度:O(n)

二分/折半查找

简介

  二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。

  因此,折半查找方法适用于不经常变动而查找频繁的有序列表。

  两个条件:1)序列有序;2)可以随机访问

查找过程

  首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

代码实现
public static int biSearch(int arr[], int target) {
	int low = 0, high = arr.length - 1;
	int mid;
	while (low <= high) {
		mid = low + (high - low) / 2; // 避免溢出
		if (arr[mid] == target)
			return mid;
		else if (arr[mid] < target)
			low = mid + 1;
		else
			high = mid - 1;
	}
	return -1;
}
性能分析

时间复杂度:O(log2(n))

因为二分查找每次排除掉一半的不适合值,所以对于 n 个元素的情况:

一次二分剩下:n/2 
两次二分剩下:n/2/2 = n/4 
……. 
m次二分剩下:n/(2^m)
在最坏情况下是在排除到只剩下最后一个值之后得到结果,即
n/(2^m)=1

所以由上式可得 : 2^m = n

进而可求出时间复杂度为:m = log2(n)

分块/索引查找

简介

  分块查找是折半查找和顺序查找的一种改进方法,分块查找由于只要求索引表是有序的,对块内节点没有排序要求 (块内无序,块间有序),因此特别适合于节点动态变化的情况。

  折半查找虽然具有很好的性能,但其前提条件时线性表顺序存储而且按照关键码排序,这一前提条件在结点树很大且表元素动态变化时是难以满足的。而顺序查找可以解决表元素动态变化的要求,但查找效率很低。如果既要保持对线性表的查找具有较快的速度,又要能够满足表元素动态变化的要求,则可采用分块查找的方法。

  当增加或减少节以及节点的关键码改变时,只需将该节点调整到所在的块即可。在空间复杂性上,分块查找的主要代价是增加了一个辅助数组。

方法描述

  分块查找要求把一个大的线性表分解成若干块,每块中的节点可以任意存放,但块与块之间必须排序。假设是按关键码值非递减的,那么这种块与块之间必须满足已排序要求,实际上就是对于任意的i,第i块中的所有节点的关键码值都必须小于第 i+1 块中的所有节点的关键码值。还要建立一个索引表(索引表中为每一块都设置索引项,每一个索引项都包含两个内容)

  • 该块的起始地址
  • 该块中最大的元素

  比如:

在这里插入图片描述

  显然,索引表是按关键字非递减顺序排列的。

  一般先用二分查找索引表,确定需要查找的关键字在哪一块,然后再在相应的块内用顺序查找。

代码实现
	public boolean search(int data) {
		int i = binarysearch(data); // 先二分查找确定在哪个块
		for (int j = 0; j < list[i].size(); j++) { // 然后顺序查找在该块内哪个位置
			if (data == (int) list[i].get(j)) {
				System.out.println(String.format("查找元素为  %d 第: %d块  第%d个 元素",data, i + 1, j + 1));
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 二分查找
	 */
	private int binarysearch(int value) {
		int start = 0;
		int end = index.length;
		int mid = -1;
		while (start <= end) {
			mid = start + (end - start) / 2;
			if (index[mid] > value) {
				end = mid - 1;
			} else {
				start = mid + 1; // 如果相等,也插入后面
			}
		}
		return start;
	}
性能分析

  这种带索引表的分块有序表查找的时间性能取决于两步查找时间之和:如前面所述,第一步可以采用简单顺序查找和折半查找之一进行。第二步只能采用简单顺序查找,但由于子表的长度较原表的长度小。因此,其时间性能介于顺序查找和折半查找之间。

  假设索引表有 n 个元素,每块含有 s 个元素,平均查找长度为:ASL = (n / s + s) / 2 + 1,时间复杂度为 O(n)~O(log2n)

综合比较

null顺序查找二分查找分块查找
表的结构有序、无序有序块内无序、块间有序
表的存储顺序、链式顺序顺序、链式
平均查找长度最大最小中间
时间复杂度O(n)O(log2n)中间

嘿嘿,公众号粉丝越来越多了,大佬,随手点个关注呗,不光有新鲜的 LeetCode 题解(多种思路,包教包会,开拓思维),还有经典的文章及短视频和大家分享,谢谢!一起嘿嘿嘿!三种静态查找算法:顺序、二分/折半、索引/分块查找
在这里插入图片描述

------致所有正在努力奋斗的程序猿们!加油!!
有码走遍天下 无码寸步难行
1024 - 梦想,永不止步!
爱编程 不爱Bug
爱加班 不爱黑眼圈
固执 但不偏执
疯狂 但不疯癫
生活里的菜鸟
工作中的大神
身怀宝藏,一心憧憬星辰大海
追求极致,目标始于高山之巅
一群怀揣好奇,梦想改变世界的孩子
一群追日逐浪,正在改变世界的极客
你们用最美的语言,诠释着科技的力量
你们用极速的创新,引领着时代的变迁

——乐于分享,共同进步,欢迎补充
——Treat Warnings As Errors
——Any comments greatly appreciated
——Talking is cheap, show me the code
——GitHub:https://github.com/selfconzrr

  • 15
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BugFree_张瑞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值